package org.eden.rpc.core.client;

import org.eden.rpc.common.entity.RpcRequest;
import org.eden.rpc.core.client.pooled.Connection;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.Map;

public class NettyClientProxy implements InvocationHandler {

    private final RpcClient client;

    private final Map<String, Object> serviceCache = new HashMap<>();

    public NettyClientProxy(RpcClient client) {
        this.client = client;
    }

    @SuppressWarnings("unchecked")
    public <T> T getService(Class<T> clazz) {
        String name = clazz.getCanonicalName();
        if (serviceCache.containsKey(name)) {
            return (T) serviceCache.get(name);
        } else {
            T service = createInstance(clazz);
            serviceCache.put(name, service);
            return service;
        }
    }

    @SuppressWarnings("unchecked")
    public <T> T createInstance(Class<T> clazz) {
        return (T) Proxy.newProxyInstance(clazz.getClassLoader(), new Class<?>[]{clazz}, this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        RpcRequest request = new RpcRequest();
        request.setInterfaceName(method.getDeclaringClass().getName());
        request.setMethodName(method.getName());
        request.setParameters(args);
        request.setParamType(method.getParameterTypes());
        return client.sendRequest(request);
    }
}
